package kevin.hbase.util;

import kevin.hbase.constant.Constant;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ConvertUtil {
    public static String getDate(byte[] data, int pos) {
        byte[] dateBytes = new byte[4];//dmyy
        System.arraycopy(data, pos, dateBytes, 0, dateBytes.length);
        return getShort(new byte[]{dateBytes[2], dateBytes[3]}) + String.format("%02d", dateBytes[1]) + String.format("%02d", dateBytes[0]);
    }

    public static String getTime(byte[] data, int pos) {
        byte[] timeBytes = new byte[3];////hms
        System.arraycopy(data, pos, timeBytes, 0, timeBytes.length);
        return String.format("%02d", timeBytes[0]) + String.format("%02d", timeBytes[1]) + String.format("%02d", timeBytes[2]);
    }

    public static String getString(byte[] data, int pos, int length, String charset) throws Exception {
        String s = new String(data, pos, length, charset);
        s = s.replaceAll("\\u0000", "");
        return s;
    }

    public static String getString(byte[] data, int pos, int length) throws Exception {
        return getString(data, pos, length, Constant.DEFAULT_CHARSET);
    }

    public static String bytes2BinaryString(byte[] bts) {
        String[] dic = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
                "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
        StringBuilder out = new StringBuilder();
        for (byte b : bts) {
            String s = String.format("%x", b);
            s = s.length() == 1 ? "0" + s : s;
            out.append(dic[Integer.parseInt(s.substring(0, 1), 16)]);
            out.append(dic[Integer.parseInt(s.substring(1, 2), 16)]);
        }
        return out.toString();
    }

    public static byte[] getShortByte(short v) {
        byte[] bs = new byte[2];
        bs[0] = (byte) ((v >>> 8) & 0xFF);
        bs[1] = (byte) ((v >>> 0) & 0xFF);

        return bs;
    }

    public static byte[] getIntByte(int v) {
        byte[] bs = new byte[4];
        bs[0] = (byte) ((v >>> 24) & 0xFF);
        bs[1] = (byte) ((v >>> 16) & 0xFF);
        bs[2] = (byte) ((v >>> 8) & 0xFF);
        bs[3] = (byte) ((v >>> 0) & 0xFF);
        return bs;
    }

    public static byte[] getLongByte(long v) {
        byte[] bs = new byte[8];
        bs[0] = (byte) (v >>> 56);
        bs[1] = (byte) (v >>> 48);
        bs[2] = (byte) (v >>> 40);
        bs[3] = (byte) (v >>> 32);
        bs[4] = (byte) (v >>> 24);
        bs[5] = (byte) (v >>> 16);
        bs[6] = (byte) (v >>> 8);
        bs[7] = (byte) (v >>> 0);

        return bs;
    }

    public static int getInt(byte[] buff) {
        return getInt(buff, 0);
    }

    public static int getInt(byte[] buff, int start) {
        int a1 = buff[start] & 0xff;
        int a2 = buff[start + 1] & 0xff;
        int a3 = buff[start + 2] & 0xff;
        int a4 = buff[start + 3] & 0xff;

        return (a1 << 24) + (a2 << 16) + (a3 << 8) + (a4 << 0);
    }

    public static long getLong(byte[] buff) {
        return getLong(buff, 0);
    }

    public static long getLong(byte[] buff, int start) {
        long a1 = buff[start] & 0xff;
        long a2 = buff[start + 1] & 0xff;
        long a3 = buff[start + 2] & 0xff;
        long a4 = buff[start + 3] & 0xff;
        long a5 = buff[start + 4] & 0xff;
        long a6 = buff[start + 5] & 0xff;
        long a7 = buff[start + 6] & 0xff;
        long a8 = buff[start + 7] & 0xff;

        return (a1 << 56) + (a2 << 48) + (a3 << 40) + (a4 << 32) + (a5 << 24) + (a6 << 16) + (a7 << 8) + (a8 << 0);
    }

    public static short getShort(byte[] buff) {
        return getShort(buff, 0);
    }

    public static short getShort(byte[] buff, int start) {
        int a1 = buff[start] & 0xff;
        int a2 = buff[start + 1] & 0xff;

        return (short) ((a1 << 8) + (a2 << 0));
    }

    public static byte[] str2bcd(String str) {
        if (str.length() % 2 != 0) {
            str = "0" + str;
        }

        byte[] buff = new byte[str.length() / 2];
        for (int step = 0; step < str.length() / 2; step++) {
            byte b1 = getBCDCharByte(str.charAt(2 * step));
            byte b2 = getBCDCharByte(str.charAt(2 * step + 1));

            buff[step] = (byte) (((b1 << 4) & 0xF0) | (b2 & 0x0F));
        }

        return buff;
    }

    private static byte getBCDCharByte(char x) {
        if (x >= '0' && x <= '9') {
            return (byte) (x - '0');
        } else {
            return (byte) (x - 'a' + 10);
        }
    }

    private static char getBCDChar(byte _lower_4bit) {
        if (_lower_4bit >= 0 && _lower_4bit <= 9) {
            return (char) ('0' + _lower_4bit);
        }

        return (char) ('a' + _lower_4bit - 10);
    }

    public static String bcd2str(byte[] bcd) {
        return bcd2str(bcd, 0, bcd.length);
    }

    public static String bcd2str(byte[] bcd, int offset) {
        return bcd2str(bcd, offset, bcd.length - offset);
    }

    public static String bcd2str(byte[] bcd, int offset, int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = offset; i < offset + length; i++) {
            byte b1 = (byte) ((bcd[i] & 0xF0) >>> 4);
            byte b0 = (byte) (bcd[i] & 0x0F);

            sb.append(getBCDChar(b1));
            sb.append(getBCDChar(b0));
        }

        return sb.toString();
    }

    public static String getBytesString(byte[] bs) {
        return getBytesString(bs, 0, bs.length);
    }

    public static String getHexString(byte[] bs) {
        return getHexString(bs, 0, bs.length, " ");
    }

    public static String getHexString(byte[] bs, String split) {
        return getHexString(bs, 0, bs.length, split);
    }

    public static String getHexString(byte[] bs, int offset, int length, String split) {
        StringBuilder info = new StringBuilder();
        for (int i = offset, count = 0; count < length; i++, count++) {
            byte b = bs[i];
            String s = Integer.toHexString(b & 0x0ff);
            if (s.length() == 1) {
                info.append("0");
            }

            info.append(s);

            if (split != null && count != length - 1) {
                info.append(split);
            }
        }

        return info.toString();
    }

    public static String getBytesString(byte[] bs, int offset, int length) {
        StringBuilder info = new StringBuilder();
        for (int i = offset, count = 0; count < length; i++, count++) {
            byte b = bs[i];
            String db = Integer.toBinaryString(b);
            if (db.length() > 8) {
                db = db.substring(db.length() - 8);
            }
            info.append(get8str(db)).append(" ");
        }
        if (info.length() > 0) {
            info.deleteCharAt(info.length() - 1);
        }

        return info.toString();
    }

    public static int indexOfZero(byte[] bs) {
        for (int i = 0; i < bs.length; i++) {
            if (bs[i] == 0x0) {
                return i;
            }
        }

        return -1;
    }

    public static int indexOfUnZero(byte[] bs) {
        for (int i = 0; i < bs.length; i++) {
            if (bs[i] != 0x0) {
                return i;
            }
        }

        return -1;
    }

    public static byte[] clearForeZero(byte[] bs) {
        int uz = indexOfUnZero(bs);
        if (uz == 0) {
            return bs;
        }

        if (uz == -1) {
            return new byte[0];
        }

        byte[] bscopy = new byte[bs.length - uz];
        System.arraycopy(bs, uz, bscopy, 0, bs.length - uz);
        return bscopy;
    }

    public static boolean equals(byte[] bs1, byte[] bs2) {
        if (bs1.length != bs2.length) {
            return false;
        }

        for (int i = 0; i < bs1.length; i++) {
            if (bs1[i] != bs2[i]) {
                return false;
            }
        }

        return true;
    }

    private static String get8str(String info) {
        int len = info.length();
        if (len < 8) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 8 - len; i++) {
                sb.append("0");
            }

            info = sb.toString() + info;
        }

        return info;
    }
}